# coding=utf-8
import os
import time
import chardet
import base64
from io import BytesIO
from PIL import Image
from django.conf import settings
from sutras import models
from sutras.enums import SutraStatus, SutraEditionStatus
from sutras.imgrecog import word_split


def save_file(fd, filename, b=True):
    try:
        if b:
            with open(filename, 'wb+') as f:
                f.write(fd.read())
                f.close()
                fd.close()
            return True
        with open(filename, 'w+') as f:
            chars = fd.read()
            chars_code = chardet.detect(chars)
            if chars_code['encoding'] != 'utf-8':
                chars = chars.decode('gbk')
            else:
                chars = chars.decode('utf-8')
            f.write(chars)
            f.close()
            fd.close()
        return True
    except Exception as e:
        return False


def get_sutra(sutra_id):
    sutra = models.Sutra.objects.filter(
        id=sutra_id).first()
    if sutra:
        return sutra
    return False


def sutra_category_list(offset, limit, getall=0):
    if int(getall) == 1:
        result = models.Sutra.objects.filter(
            status=SutraStatus.normal).order_by('-id')
    else:
        result = models.Sutra.objects.filter(
            status=SutraStatus.normal).order_by(
            '-id')[offset: offset + limit]
    if not result:
        return []
    data = []
    for res in result:
        data.append({
            'id': res.id,
            'name': res.name,
            'desc': res.description})
    return data


def handel_sutra_img(cover_img):
    ext = os.path.splitext(cover_img.name)[1]
    imgname = '{0}{1}'.format(int(time.time() * 1000000), ext)
    img_url = settings.SUTRAS_COVERURL_URL + imgname
    filename = '{0}{1}'.format(settings.SUTRAS_COVER_PATH, imgname)
    save_file(cover_img, filename)
    return img_url


def create_sutra_category(name, desc, img_url):
    return models.Sutra.objects.create(**{
        'name': name,
        'description': desc,
        'cover_url': img_url})


def get_sutra_category(sutra_id):
    sutra = models.Sutra.objects.filter(id=sutra_id).first()
    if not sutra:
        return False
    return {
        'name': sutra.name,
        'desc': sutra.description,
        'cover_img_url': '{0}{1}'.format(
            settings.SELF_DOMAIN, sutra.cover_url)}


def update_sutra_category(sutra_id, update_data):
    if not update_data:
        return
    sutra = models.Sutra.objects.filter(id=sutra_id).first()
    if not sutra:
        return False
    for key, value in update_data.items():
        if value:
            sutra.__dict__[key] = value
    sutra.save()
    return True


def del_sutra_category(sutra_id, delete=False):
    sutra = models.Sutra.objects.filter(id=sutra_id).first()
    if not sutra:
        return
    if delete:
        sutra.delete()
        return
    sutra.status = SutraStatus.delete
    sutra.save()


def sutra_edition_list(sutra_id, offset, limit):
    if limit == 0:
        result = models.SutraEdition.objects.filter(
            status=SutraEditionStatus.normal)
        if sutra_id:
            result = result.filter(sutra_id=sutra_id)
    else:
        result = models.SutraEdition.objects.filter(
            status=SutraEditionStatus.normal)
        if sutra_id:
            result = result.filter(sutra_id=sutra_id)
        result = result[offset: offset + limit]
    if not result:
        return []
    edition_sutra = dict(result.values_list('id', 'sutra_id'))
    sutra_name = dict(models.Sutra.objects.filter(
        id__in=edition_sutra.values).values_list('id', 'name'))
    data = []
    for res in result:
        data.append({
            'id': res.id,
            'sutra_name': sutra_name.get(edition_sutra[res.id]),
            'name': res.name,
            'total_page_num': res.total_page_num,
            'price': res.price,
            'cover_img_url': '{0}{1}'.format(
                settings.SELF_DOMAIN, res.cover_url),
            'art_no': res.art_no})
    return data


def get_edition(edition_id):
    edition = models.SutraEdition.objects.filter(
        id=edition_id).first()
    if edition:
        return edition
    return False


def create_sutra_edition(create_data):
    return models.SutraEdition.objects.create(**create_data)


def update_sutra_edition(edition, update_data):
    if not update_data:
        return
    for key, value in update_data.items():
        if value:
            edition.__dict__[key] = value
    edition.save()


def get_edition_details(edition_id):
    edition = models.SutraEdition.objects.filter(
        id=edition_id).first()
    if not edition:
        return False
    page = models.SutraEditionPage.objects.filter(
        sutra_edition_id=edition_id).order_by(
            '-page_num').first()
    max_page_num = 0
    if page:
        max_page_num = page.page_num
    return {
        'name': edition.name,
        'sutra_id': edition.sutra_id,
        'desc': edition.description,
        'cover_url': '{0}{1}'.format(
            settings.SELF_DOMAIN, edition.cover_url),
        'author': edition.author,
        'total_page_num': edition.total_page_num,
        'total_char_num': edition.total_char_num,
        'char_url': '{0}{1}'.format(
            settings.SELF_DOMAIN, edition.char_url),
        'price': edition.price,
        'print_price': edition.print_price,
        'default_type_page_info': {
            'max_page_num': max_page_num}}


def no_import_page(edition_id, need_num):
    edition = models.SutraEdition.objects.filter(
        id=edition_id).first()
    pages = models.SutraEditionPage.objects.filter(
        sutra_edition=edition).order_by('page_num').values_list(
        'page_num', flat=True)
    data = {
        'edition_id': edition_id,
        'total_page_num': len(pages),
        'pages': []}
    n = 1
    for i in range(edition.total_page_num):
        if n > need_num:
            break
        if (i + 1) not in pages:
            data['pages'].append({
                'page_num': i + 1})
            n += 1
    return data


def del_sutra_edition(edition_id, delete=False):
    edition = models.SutraEdition.objects.filter(
        id=edition_id).first()
    if not edition:
        return
    if delete:
        edition.delete()
        return
    edition.status = SutraEditionStatus.delete
    edition.save()


def edition_page_list(edition_id, offset, limit):
    objects = models.SutraEditionPage.objects
    if edition_id:
        result = objects.filter(
            sutra_edition_id=edition_id).order_by(
            'page_num')[offset: offset + limit]
    else:
        result = objects.filter().order_by(
            'page_num')[offset: offset + limit]
    if not result:
        return []
    # page_edition_ids: page_id->edition_id
    page_edition_ids = dict(result.values_list('id', 'sutra_edition_id'))
    editions = models.SutraEdition.objects.filter(
        id__in=page_edition_ids.values())
    # edition_names: edition_id->name
    edition_names = dict(editions.values_list('id', 'name'))
    # edition_sutra_ids: edition_id->sutra_id
    edition_sutra_ids = dict(editions.values_list('id', 'sutra_id'))
    # sutras_names: sutra_id->name
    sutras_names = dict(models.Sutra.objects.filter(
        id__in=edition_sutra_ids.values()).values_list('id', 'name'))

    data = []
    for res in result:
        sutra_id = edition_sutra_ids[page_edition_ids[res.id]]
        data.append({
            'id': res.id,
            'sutra_id': sutra_id,
            'sutra_name': sutras_names[sutra_id],
            'edition_id': page_edition_ids[res.id],
            'edition_name': edition_names[page_edition_ids[res.id]],
            'page_num': res.page_num,
            'status': res.status,
            'original_cimg_url': '{0}{1}'.format(
                settings.SELF_DOMAIN, res.original_cimg_url),
            'hyaline_cimg_url': '{0}{1}'.format(
                settings.SELF_DOMAIN, res.hyaline_cimg_url)})
    return data


def handel_edition_img(cover_img, edition_id):
    # if cover_img:
    ext = os.path.splitext(cover_img.name)[1]
    imgname = '{0}{1}'.format(int(time.time() * 1000000), ext)
    folder = '{0}{1}/'.format(
        settings.SUTRAS_EDITION_COVER_PATH, edition_id)
    if not os.path.exists(folder):
        os.makedirs(folder)
    filename = '{0}{1}'.format(folder, imgname)
    save_file(cover_img, filename)
    img_url = '{0}{1}/{2}'.format(
        settings.SUTRAS_EDITION_COVERURL_URL, edition_id, imgname)
    return img_url


def handel_edition_char(txt, edition_id):
    ext = os.path.splitext(txt.name)[1]
    txtname = '{0}{1}'.format('char', ext)
    folder = '{0}{1}/'.format(
        settings.SUTRAS_EDITION_CHAR_PATH, edition_id)
    if not os.path.exists(folder):
        os.makedirs(folder)
    filename = '{0}{1}'.format(folder, txtname)
    save_file(txt, filename, b=False)
    txt_url = '{0}{1}/{2}'.format(
        settings.SUTRAS_EDITION_CHAR_URL, edition_id, txtname)
    # 文字定位临时文件
    psfilename = '{0}{1}'.format(folder, 'ps.txt')
    num = 0
    txt_f = open(filename, 'r')
    chars = txt_f.read()
    txt_f.close()
    with open(psfilename, 'w') as ps_f:
        chars = chars.replace(' ', '')
        chars = chars.replace('\r\n', '')
        chars = chars.replace('\n', '')
        num = len(chars)
        ps_f.write(chars)
    return num, txt_url


def handle_page_img(edition_id, content_img, page_num):
    folder = settings.EDITION_PAGE_PATH.format(edition_id)
    if not os.path.exists(folder):
        os.makedirs(folder)
    ext = os.path.splitext(content_img.name)[1]
    imgname = '{0}{1}'.format(page_num, ext)
    hyaline_imgname = 'hy{0}{1}'.format(page_num, ext)
    twov_imgname = 'twov{0}{1}'.format(page_num, ext)

    filename = '{0}{1}'.format(folder, imgname)
    hyaline_filename = '{0}{1}'.format(folder, hyaline_imgname)
    twov_filename = '{0}{1}'.format(folder, twov_imgname)
    save_file(content_img, filename)
    img_2v, sf = make_hyaline_img(filename, hyaline_filename)
    img_2v.save(twov_filename)
    original_cimg_url = '{0}{1}'.format(
        settings.EDITION_PAGE_URL.format(edition_id), imgname)
    hyaline_cimg_url = '{0}{1}'.format(
        settings.EDITION_PAGE_URL.format(edition_id),
        hyaline_imgname)
    twov_cimg_url = '{0}{1}'.format(
        settings.EDITION_PAGE_URL.format(edition_id),
        twov_imgname)
    return {
        'original_cimg_url': original_cimg_url,
        'hyaline_cimg_url': hyaline_cimg_url,
        'twov_cimg_url': twov_cimg_url,
        'sf': sf}


def make_hyaline_img(imgpath, save_filename):
    img_2v, sf = word_split.get_img_2v(img_path=imgpath)
    word_split.save_hyaline_img_2v(img_2v, save_filename)
    return img_2v, sf


def create_edition_page(edition_id, create_data):
    return models.SutraEditionPage.objects.create(**create_data)


def del_edition_page(page_id, delete=False):
    page = models.SutraEditionPage.objects.filter(
        id=page_id).first()
    page_num = page.page_num
    if not page:
        return None
    if page.status == 1:
        return False
    page.delete()
    gt_pages = models.SutraEditionPage.objects.filter(
        page_num__gt=page_num,
        sutra_edition_id=page.sutra_edition_id).order_by('page_num')
    for gt_page in gt_pages:
        gt_page.page_num = gt_page.page_num - 1
        gt_page.save()
    return True


def update_edition_page(page, update_data):
    if not update_data:
        return
    for key, value in update_data.items():
        if value:
            page.__dict__[key] = value
    page.save()


def get_edition_page(page_id, return_obj=True):
    edition_page = models.SutraEditionPage.objects.filter(
        id=page_id).first()
    if not edition_page:
        return None
    if return_obj is True:
        return edition_page
    return {
        'status': edition_page.status,
        'edition_id': edition_page.sutra_edition.id,
        'id': edition_page.id,
        'edition_name': edition_page.sutra_edition.name,
        'content': edition_page.content,
        'page_num': edition_page.page_num,
        'original_cimg_url': '{0}{1}'.format(
            settings.SELF_DOMAIN, edition_page.original_cimg_url),
        'hyaline_cimg_url': '{0}{1}'.format(
            settings.SELF_DOMAIN, edition_page.hyaline_cimg_url),
        'total_char_num': edition_page.total_char_num,
        'create_time': edition_page.create_time}


def get_edition_page_by_pagenum(edition_id, page_num, return_obj=True):
    edition_page = models.SutraEditionPage.objects.filter(
        sutra_edition_id=edition_id,
        page_num=page_num).first()
    if not edition_page:
        return False
    if return_obj is True:
        return edition_page
    return {
        'edition_id': edition_page.sutra_edition.id,
        'id': edition_page.id,
        'edition_name': edition_page.sutra_edition.name,
        'content': edition_page.content,
        'page_num': page_num,
        'original_cimg_url': '{0}{1}'.format(
            settings.SELF_DOMAIN, edition_page.original_cimg_url),
        'hyaline_cimg_url': '{0}{1}'.format(
            settings.SELF_DOMAIN, edition_page.hyaline_cimg_url),
        'total_char_num': edition_page.total_char_num,
        'create_time': edition_page.create_time}


def edition_page_scan(page_id):
    page = models.SutraEditionPage.objects.filter(
        id=page_id).first()
    if not page:
        return False
    return {
        'hyaline_cimg_url': '{0}{1}'.format(
            settings.SELF_DOMAIN, page.hyaline_cimg_url),
        'page_num': page.page_num}


# def edition_page_recog(page_id, typeset, content):
#     page = models.SutraEditionPage.objects.filter(
#         id=page_id).first()
#     if not page:
#         return False
#     twovimgpath = '{0}{1}'.format(
#         settings.BASE_DIR, page.twov_cimg_url)
#     folder = settings.PAGE_WORD_PATH.format(
#         page.sutra_edition_id, page.page_num)
#     if not os.path.exists(folder):
#         os.makedirs(folder)
#     trans = True if typeset == 1 else False
#     wnames = word_split.save_words_img(
#         twovimgpath, float(page.sf), folder,
#         trans=trans, hyaline=True)
#     data = []
#     models.SutraEditionChar.objects.filter(
#         page_id=page.id,
#         page_num=page.page_num).delete()
#     max_index = 0
#     for key, value in wnames.items():
#         word_url = '{0}{1}'.format(settings.PAGE_WORD_URL.format(
#             page.sutra_edition_id, page.page_num), value['name'])
#         try:
#             text = content[key]
#         except Exception as e:
#             text = 'no'
#         data.append({
#             'word_url': '{0}{1}'.format(
#                 settings.SELF_DOMAIN, word_url),
#             'x': value['x'],
#             'y': value['y'],
#             'text': text})
#         models.SutraEditionChar.objects.create(**{
#             'page_id': page.id,
#             'page_num': page.page_num, 'index': key,
#             'img_url': word_url, 'text': text,
#             'x_positions': json.dumps(value['x']),
#             'y_positions': json.dumps(value['y'])})
#         if key > max_index:
#             max_index = key
#     page.content = content
#     page.total_char_num = max_index + 1
#     page.save()
#     return data


def _get_img_words_status0(page, edition_id):
    twovimgpath = '{0}{1}'.format(
        settings.BASE_DIR, page.twov_cimg_url)
    folder = settings.PAGE_WORD_PATH.format(
        page.sutra_edition_id, page.page_num)
    if not os.path.exists(folder):
        os.makedirs(folder)
    wnames = word_split.save_words_img(
        twovimgpath, float(page.sf), folder,
        hyaline=True)
    data = {
        'words': [], 'extra_w': [], 'word_imgurl': [],
        'page_id': page.id, 'status': 0}
    words_num = len(wnames)
    char_folder = '{0}{1}/'.format(
        settings.SUTRAS_EDITION_CHAR_PATH, page.sutra_edition.id)
    # 文字定位临时文件
    psfilename = '{0}{1}'.format(char_folder, 'ps.txt')
    with open(psfilename, 'r') as ps_f:
        words = ps_f.read()
    for key, value in wnames.items():
        word_url = '{0}{1}'.format(settings.PAGE_WORD_URL.format(
            page.sutra_edition_id, page.page_num), value['name'])
        data['word_imgurl'].append('{0}{1}'.format(
            settings.SELF_DOMAIN, word_url))
    data['words'] = list(words[0:words_num])
    data['extra_w'] = list(words[words_num:words_num * 2])
    return data


def _get_img_words_status1(page, edition_id):
    chars = models.SutraEditionChar.objects.filter(page=page)
    data = {
        'words': [], 'word_imgurl': [],
        'page_id': page.id, 'status': 1}
    for char in chars:
        data['words'].append(char.text)
        word_url = '{0}{1}'.format(settings.PAGE_WORD_URL.format(
            page.sutra_edition_id, page.page_num), char.img_url)
        data['word_imgurl'].append(word_url)
    return data


def get_img_words(page_id, edition_id):
    page = models.SutraEditionPage.objects.filter(
        id=page_id).first()
    if not page:
        return False
    if page.status == 0:
        return _get_img_words_status0(page, edition_id)
    else:
        return _get_img_words_status1(page, edition_id)


def base64_to_img(base64img):
    return Image.open(BytesIO(base64.b64decode(base64img)))


def save_hyaline_img(img, page_id, edition_id):
    img, sf = word_split.get_img_2v(img=img)
    page = models.SutraEditionPage.objects.filter(
        id=page_id).first()
    name = '{0}.png'.format(int(time.time() * 10000))
    folder = settings.PAGE_WORD_PATH.format(
        edition_id, page.page_num)
    filename = '{0}{1}'.format(
        folder, name)
    word_split.save_hyaline_img_2v(img, filename)
    word_url = '{0}{1}'.format(
        settings.PAGE_WORD_URL.format(
            edition_id, page.page_num), name)
    word_url = '{0}{1}'.format(settings.SELF_DOMAIN, word_url)
    return word_url


def page_word_location(page_id, edition_id, word_imgurl, words):
    page = models.SutraEditionPage.objects.filter(
        id=page_id).first()
    if not page:
        return False
    max_index_char = models.SutraEditionChar.objects.filter(
        page=page).order_by('-index').first()
    max_index = 0
    if max_index_char is not None:
        max_index = max_index_char.index + 1
    lenth = len(words)
    for i in range(lenth):
        models.SutraEditionChar.objects.create(**{
            'page': page,
            'page_num': page.page_num,
            'index': max_index + i,
            # 'index': 0,
            'text': words[i],
            'img_url': word_imgurl[i].split('/')[-1]})
    page.status = 1
    page.total_char_num = lenth
    page.save()
    folder = '{0}{1}/'.format(
        settings.SUTRAS_EDITION_CHAR_PATH, edition_id)
    psfilename = '{0}{1}'.format(folder, 'ps.txt')
    with open(psfilename, 'r') as ps_f:
        chars = ps_f.read()
    chars = chars[lenth:]
    with open(psfilename, 'w') as ps_f:
        ps_f.write(chars)
    return True
